﻿#pragma execution_character_set("utf-8")

#include "kminicalendaritem.h"
#include "qpainter.h"
#include "qevent.h"
#include "qdatetime.h"
#include "qdebug.h"

namespace kdk
{
class KMiniCalendarItemPrivate : public QObject
{
    Q_OBJECT
    Q_DECLARE_PUBLIC(KMiniCalendarItem)
public:
    KMiniCalendarItemPrivate(KMiniCalendarItem* parent);

private:
    KMiniCalendarItem* q_ptr;
    KMiniCalendarItem::SelectType selectType;          //选中模式
    KMiniCalendarItem::DayType dayType;                //当前日类型
    bool hover;                     //鼠标是否悬停
    bool pressed;                   //鼠标是否按下

    bool select;                    //是否选中
    bool showLunar;                 //显示农历
    bool enableBorder;              //显示边框

    QDate date;                     //当前日期
    QString lunar;                  //农历信息

    QColor borderColor;             //边框颜色
    QColor weekColor;               //周末颜色
    QColor superColor;              //角标颜色
    QColor lunarColor;              //农历节日颜色

    QColor currentTextColor;        //当前月文字颜色
    QColor otherTextColor;          //其他月文字颜色
    QColor selectTextColor;         //选中日期文字颜色
    QColor hoverTextColor;          //悬停日期文字颜色

    QColor currentLunarColor;       //当前月农历文字颜色
    QColor otherLunarColor;         //其他月农历文字颜色
    QColor selectLunarColor;        //选中日期农历文字颜色
    QColor hoverLunarColor;         //悬停日期农历文字颜色

    QColor currentBgColor;          //当前月背景颜色
    QColor otherBgColor;            //其他月背景颜色
    QColor selectBgColor;           //选中日期背景颜色
    QColor hoverBgColor;            //悬停日期背景颜色
};

KMiniCalendarItemPrivate::KMiniCalendarItemPrivate(KMiniCalendarItem* parent) : q_ptr(parent)
{
    Q_Q(KMiniCalendarItem);
    hover = false;
    pressed = false;

    select = false;
    showLunar = true;
    enableBorder = false;
    selectType = KMiniCalendarItem::SelectType_Rect;

    date = QDate::currentDate();
    lunar = "初一";
    dayType = KMiniCalendarItem::DayType_MonthCurrent;

    borderColor = QColor(180, 180, 180);
    weekColor = QColor(255, 0, 0);
    superColor = QColor(255, 129, 6);
    lunarColor = QColor(55, 156, 238);

    currentTextColor = QColor(0, 0, 0);
    otherTextColor = QColor(200, 200, 200);
    selectTextColor = QColor(255, 255, 255);
    hoverTextColor = QColor(250, 250, 250);

    currentLunarColor = QColor(150, 150, 150);
    otherLunarColor = QColor(200, 200, 200);
    selectLunarColor = QColor(255, 255, 255);
    hoverLunarColor = QColor(250, 250, 250);

    currentBgColor = QColor(255, 255, 255);
    otherBgColor = QColor(240, 240, 240);
    selectBgColor = QColor(208, 47, 18);
    hoverBgColor = QColor(204, 183, 180);
}

KMiniCalendarItem::KMiniCalendarItem(QWidget *parent) : QWidget(parent), d_ptr(new KMiniCalendarItemPrivate(this))
{
    Q_D(KMiniCalendarItem);
}

void KMiniCalendarItem::enterEvent(QEvent *)
{
    Q_D(KMiniCalendarItem);
    d->hover = true;
    update();
}

void KMiniCalendarItem::leaveEvent(QEvent *)
{
    Q_D(KMiniCalendarItem);
    d->hover = false;
    update();
}

void KMiniCalendarItem::mousePressEvent(QMouseEvent *)
{
    Q_D(KMiniCalendarItem);
    d->pressed = true;
    update();

    emit clicked(d->date, d->dayType);
}

void KMiniCalendarItem::mouseReleaseEvent(QMouseEvent *)
{
    Q_D(KMiniCalendarItem);
    d->pressed = false;
    update();
}

void KMiniCalendarItem::paintEvent(QPaintEvent *)
{
    Q_D(KMiniCalendarItem);
    //绘制准备工作,启用反锯齿
    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);

    //绘制背景和边框
    drawBg(&painter);

    //优先绘制选中状态,其次绘制悬停状态
    if (d->select)
    {
        drawBgCurrent(&painter, d->selectBgColor);
    }
    else if (d->hover)
    {
        drawBgCurrent(&painter, d->hoverBgColor);
    }

    //绘制日期
    drawDay(&painter);

    //绘制农历信息
    drawLunar(&painter);
}

void KMiniCalendarItem::drawBg(QPainter *painter)
{
    Q_D(KMiniCalendarItem);
    painter->save();

    //根据当前类型选择对应的颜色
    QColor bgColor = d->currentBgColor;

    if (d->dayType == DayType_MonthPre || d->dayType == DayType_MonthNext)
    {
        bgColor = d->otherBgColor;
    }

    if(getEnableBorder())
        painter->setPen(d->borderColor);
    else
        painter->setPen(bgColor);

    painter->setBrush(bgColor);
    painter->drawRect(rect());

    painter->restore();
}

void KMiniCalendarItem::drawBgCurrent(QPainter *painter, const QColor &color)
{
    Q_D(KMiniCalendarItem);
    int width = this->width();
    int height = this->height();
    int side = qMin(width, height);

    painter->save();

    painter->setPen(Qt::NoPen);
    painter->setBrush(color);

    //根据设定绘制背景样式
    if (d->selectType == SelectType_Rect)
    {
        painter->drawRect(rect());
    }
    else if (d->selectType == SelectType_Circle)
    {
        int radius = side / 2;
        painter->drawEllipse(QPointF(width / 2, height / 2), radius, radius);
    }
    else if (d->selectType == SelectType_Triangle)
    {
        int radius = side / 3;
        QPolygon pts;
        pts.setPoints(3, 1, 1, radius, 1, 1, radius);
        painter->drawRect(rect());
        painter->setBrush(d->superColor);
        painter->drawConvexPolygon(pts);
    }

    painter->restore();
}

void KMiniCalendarItem::drawDay(QPainter *painter)
{
    Q_D(KMiniCalendarItem);
    int width = this->width();
    int height = this->height();
    int side = qMin(width, height);

    painter->save();

    //根据当前类型选择对应的颜色
    QColor color = d->currentTextColor;

    if (d->dayType == DayType_MonthPre || d->dayType == DayType_MonthNext)
    {
        color = d->otherTextColor;
    }
    else if (d->dayType == DayType_WeekEnd)
    {
        color = d->weekColor;
    }

    if (d->select)
    {
        color = d->selectTextColor;
    }
    else if (d->hover)
    {
        color = d->hoverTextColor;
    }

    painter->setPen(color);

    if (d->showLunar)
    {
        QFont font;
        font.setPixelSize(side / 2.7);
        painter->setFont(font);

        QRect dayRect = QRect(0, 0, width, height / 1.5);
        painter->drawText(dayRect, Qt::AlignHCenter | Qt::AlignBottom, QString::number(d->date.day()));
    }
    else
    {
        QFont font;
        font.setPixelSize(side / 2);
        painter->setFont(font);

        QRect dayRect = QRect(0, 0, width, height);
        painter->drawText(dayRect, Qt::AlignCenter, QString::number(d->date.day()));
    }

    painter->restore();
}

void KMiniCalendarItem::drawLunar(QPainter *painter)
{
    Q_D(KMiniCalendarItem);

    if (!d->showLunar)
    {
        return;
    }

    int width = this->width();
    int height = this->height();
    int side = qMin(width, height);

    painter->save();

    QStringList listDayName;
    listDayName << "*" << "初一" << "初二" << "初三" << "初四" << "初五" << "初六" << "初七" << "初八" << "初九" << "初十"
                << "十一" << "十二" << "十三" << "十四" << "十五" << "十六" << "十七" << "十八" << "十九" << "二十"
                << "廿一" << "廿二" << "廿三" << "廿四" << "廿五" << "廿六" << "廿七" << "廿八" << "廿九" << "三十";

    //根据当前类型选择对应的颜色
    QColor color = d->currentLunarColor;

    if (d->dayType == DayType_MonthPre || d->dayType == DayType_MonthNext)
    {
        color = d->otherLunarColor;
    }

    if (d->select)
    {
        color = d->selectTextColor;
    }
    else if (d->hover)
    {
        color = d->hoverTextColor;
    }

    painter->setPen(color);

    QFont font;
    font.setPixelSize(side / 4);
    font.setBold(true);
    painter->setFont(font);

    QRect lunarRect(0, height / 2, width, height / 2.2);
    painter->drawText(lunarRect, Qt::AlignCenter, d->lunar);

    painter->restore();
}

bool KMiniCalendarItem::getSelect() const
{
    Q_D(const KMiniCalendarItem);
    return d->select;
}

bool KMiniCalendarItem::getShowLunar() const
{
    Q_D(const KMiniCalendarItem);
    return d->showLunar;
}

bool KMiniCalendarItem::getEnableBorder() const
{
    Q_D(const KMiniCalendarItem);
    return d->enableBorder;
}

KMiniCalendarItem::SelectType KMiniCalendarItem::getSelectType() const
{
    Q_D(const KMiniCalendarItem);
    return d->selectType;
}

QDate KMiniCalendarItem::getDate() const
{
    Q_D(const KMiniCalendarItem);
    return d->date;
}

QString KMiniCalendarItem::getLunar() const
{
    Q_D(const KMiniCalendarItem);
    return d->lunar;
}

KMiniCalendarItem::DayType KMiniCalendarItem::getDayType() const
{
    Q_D(const KMiniCalendarItem);
    return d->dayType;
}

QColor KMiniCalendarItem::getBorderColor() const
{
    Q_D(const KMiniCalendarItem);
    return d->borderColor;
}

QColor KMiniCalendarItem::getWeekColor() const
{
    Q_D(const KMiniCalendarItem);
    return d->weekColor;
}

QColor KMiniCalendarItem::getSuperColor() const
{
    Q_D(const KMiniCalendarItem);
    return d->superColor;
}

QColor KMiniCalendarItem::getLunarColor() const
{
    Q_D(const KMiniCalendarItem);
    return d->lunarColor;
}

QColor KMiniCalendarItem::getCurrentTextColor() const
{
    Q_D(const KMiniCalendarItem);
    return d->currentTextColor;
}

QColor KMiniCalendarItem::getOtherTextColor() const
{
    Q_D(const KMiniCalendarItem);
    return d->otherTextColor;
}

QColor KMiniCalendarItem::getSelectTextColor() const
{
    Q_D(const KMiniCalendarItem);
    return d->selectTextColor;
}

QColor KMiniCalendarItem::getHoverTextColor() const
{
    Q_D(const KMiniCalendarItem);
    return d->hoverTextColor;
}

QColor KMiniCalendarItem::getCurrentLunarColor() const
{
    Q_D(const KMiniCalendarItem);
    return d->currentLunarColor;
}

QColor KMiniCalendarItem::getOtherLunarColor() const
{
    Q_D(const KMiniCalendarItem);
    return d->otherLunarColor;
}

QColor KMiniCalendarItem::getSelectLunarColor() const
{
    Q_D(const KMiniCalendarItem);
    return d->selectLunarColor;
}

QColor KMiniCalendarItem::getHoverLunarColor() const
{
    Q_D(const KMiniCalendarItem);
    return d->hoverLunarColor;
}

QColor KMiniCalendarItem::getCurrentBgColor() const
{
    Q_D(const KMiniCalendarItem);
    return d->currentBgColor;
}

QColor KMiniCalendarItem::getOtherBgColor() const
{
    Q_D(const KMiniCalendarItem);
    return d->otherBgColor;
}

QColor KMiniCalendarItem::getSelectBgColor() const
{
    Q_D(const KMiniCalendarItem);
    return d->selectBgColor;
}

QColor KMiniCalendarItem::getHoverBgColor() const
{
    Q_D(const KMiniCalendarItem);
    return d->hoverBgColor;
}

QSize KMiniCalendarItem::sizeHint() const
{
    Q_D(const KMiniCalendarItem);
    return QSize(100, 100);
}

QSize KMiniCalendarItem::minimumSizeHint() const
{
    Q_D(const KMiniCalendarItem);
    return QSize(20, 20);
}

void KMiniCalendarItem::setSelect(bool select)
{
    Q_D(KMiniCalendarItem);

    if (d->select != select)
    {
        d->select = select;
        update();
    }
}

void KMiniCalendarItem::setShowLunar(bool showLunar)
{
    Q_D(KMiniCalendarItem);

    if (d->showLunar != showLunar)
    {
        d->showLunar = showLunar;
        update();
    }
}

void KMiniCalendarItem::setSelectType(const KMiniCalendarItem::SelectType &selectType)
{
    Q_D(KMiniCalendarItem);

    if(d->selectType != selectType)
    {
        d->selectType = selectType;
        update();
    }
}

void KMiniCalendarItem::setDate(const QDate &date)
{
    Q_D(KMiniCalendarItem);

    if (d->date != date)
    {
        d->date = date;
        update();
    }
}

void KMiniCalendarItem::setLunar(const QString &lunar)
{
    Q_D(KMiniCalendarItem);

    if (d->lunar != lunar)
    {
        d->lunar = lunar;
        update();
    }
}

void KMiniCalendarItem::setDayType(const DayType &dayType)
{
    Q_D(KMiniCalendarItem);

    if (d->dayType != dayType)
    {
        d->dayType = dayType;
        update();
    }
}

void KMiniCalendarItem::setDate(const QDate &date, const QString &lunar, const DayType &dayType)
{
    Q_D(KMiniCalendarItem);
    d->date = date;
    d->lunar = lunar;
    d->dayType = dayType;
    update();
}

void KMiniCalendarItem::setEnableBorder(bool bVisible)
{
    Q_D(KMiniCalendarItem);

    if (d->enableBorder != bVisible)
    {
        d->enableBorder = bVisible;
        update();
    }
}

void KMiniCalendarItem::setBorderColor(const QColor &borderColor)
{
    Q_D(KMiniCalendarItem);

    if (d->borderColor != borderColor)
    {
        d->borderColor = borderColor;
        update();
    }
}

void KMiniCalendarItem::setWeekColor(const QColor &weekColor)
{
    Q_D(KMiniCalendarItem);

    if (d->weekColor != weekColor)
    {
        d->weekColor = weekColor;
        update();
    }
}

void KMiniCalendarItem::setSuperColor(const QColor &superColor)
{
    Q_D(KMiniCalendarItem);

    if (d->superColor != superColor)
    {
        d->superColor = superColor;
        update();
    }
}

void KMiniCalendarItem::setLunarColor(const QColor &lunarColor)
{
    Q_D(KMiniCalendarItem);

    if (d->lunarColor != lunarColor)
    {
        d->lunarColor = lunarColor;
        update();
    }
}

void KMiniCalendarItem::setCurrentTextColor(const QColor &currentTextColor)
{
    Q_D(KMiniCalendarItem);

    if (d->currentTextColor != currentTextColor)
    {
        d->currentTextColor = currentTextColor;
        update();
    }
}

void KMiniCalendarItem::setOtherTextColor(const QColor &otherTextColor)
{
    Q_D(KMiniCalendarItem);

    if (d->otherTextColor != otherTextColor)
    {
        d->otherTextColor = otherTextColor;
        update();
    }
}

void KMiniCalendarItem::setSelectTextColor(const QColor &selectTextColor)
{
    Q_D(KMiniCalendarItem);

    if (d->selectTextColor != selectTextColor)
    {
        d->selectTextColor = selectTextColor;
        update();
    }
}

void KMiniCalendarItem::setHoverTextColor(const QColor &hoverTextColor)
{
    Q_D(KMiniCalendarItem);

    if (d->hoverTextColor != hoverTextColor)
    {
        d->hoverTextColor = hoverTextColor;
        update();
    }
}

void KMiniCalendarItem::setCurrentLunarColor(const QColor &currentLunarColor)
{
    Q_D(KMiniCalendarItem);

    if (d->currentLunarColor != currentLunarColor)
    {
        d->currentLunarColor = currentLunarColor;
        update();
    }
}

void KMiniCalendarItem::setOtherLunarColor(const QColor &otherLunarColor)
{
    Q_D(KMiniCalendarItem);

    if (d->otherLunarColor != otherLunarColor)
    {
        d->otherLunarColor = otherLunarColor;
        update();
    }
}

void KMiniCalendarItem::setSelectLunarColor(const QColor &selectLunarColor)
{
    Q_D(KMiniCalendarItem);

    if (d->selectLunarColor != selectLunarColor)
    {
        d->selectLunarColor = selectLunarColor;
        update();
    }
}

void KMiniCalendarItem::setHoverLunarColor(const QColor &hoverLunarColor)
{
    Q_D(KMiniCalendarItem);

    if (d->hoverLunarColor != hoverLunarColor)
    {
        d->hoverLunarColor = hoverLunarColor;
        update();
    }
}

void KMiniCalendarItem::setCurrentBgColor(const QColor &currentBgColor)
{
    Q_D(KMiniCalendarItem);

    if (d->currentBgColor != currentBgColor)
    {
        d->currentBgColor = currentBgColor;
        update();
    }
}

void KMiniCalendarItem::setOtherBgColor(const QColor &otherBgColor)
{
    Q_D(KMiniCalendarItem);

    if (d->otherBgColor != otherBgColor)
    {
        d->otherBgColor = otherBgColor;
        update();
    }
}

void KMiniCalendarItem::setSelectBgColor(const QColor &selectBgColor)
{
    Q_D(KMiniCalendarItem);

    if (d->selectBgColor != selectBgColor)
    {
        d->selectBgColor = selectBgColor;
        update();
    }
}

void KMiniCalendarItem::setHoverBgColor(const QColor &hoverBgColor)
{
    Q_D(KMiniCalendarItem);

    if (d->hoverBgColor != hoverBgColor)
    {
        d->hoverBgColor = hoverBgColor;
        update();
    }
}
}

#include "kminicalendaritem.moc"
#include "moc_kminicalendaritem.cpp"
